'use strict';

module.exports = () => {
  return async function errorHandler(ctx, next) {
    try {
      await next();
    } catch (err) {
      // 记录错误日志
      ctx.app.emit('error', err, ctx);

      // 获取错误信息
      let status = err.status || err.statusCode || 500;
      let message = getErrorMessage(err);

      // 特殊错误类型处理
      const errorType = detectErrorType(err);

      switch (errorType) {
        case 'SEQUELIZE_UNKNOWN_COLUMN':
          status = 500;
          message = '数据库字段配置错误，请联系管理员';
          break;

        case 'SEQUELIZE_UNKNOWN_TABLE':
          status = 500;
          message = '数据库表配置错误，请联系管理员';
          break;

        case 'SEQUELIZE_SYNTAX_ERROR':
          status = 500;
          message = '数据库查询语法错误，请联系管理员';
          break;

        case 'SEQUELIZE_DATABASE_ERROR':
          status = 500;
          message = '数据库操作失败，请稍后重试';
          break;

        case 'SEQUELIZE_ASSOCIATION':
          status = 500;
          message = '数据关联配置错误，请联系管理员';
          break;

        case 'SEQUELIZE_VALIDATION':
          status = 400;
          message = '数据验证失败';
          break;

        case 'SEQUELIZE_UNIQUE':
          status = 409;
          message = '数据已存在，请检查唯一性约束';
          break;

        case 'SEQUELIZE_FOREIGN_KEY':
          status = 400;
          message = '关联数据不存在';
          break;

        case 'JWT_ERROR':
          status = 401;
          message = 'Token无效或已过期';
          break;

        case 'MYSQL_CONNECTION':
          status = 503;
          message = '数据库连接失败，请稍后重试';
          break;

        default:
          // 保持原有逻辑
          break;
      }

      // 设置响应状态码
      ctx.status = status;

      // 根据错误类型设置响应
      if (status === 422) {
        // 参数验证错误
        ctx.body = {
          code: 422,
          message: '参数验证失败',
          errors: err.errors || [],
        };
      } else if (status === 401) {
        // 认证错误
        ctx.body = {
          code: 401,
          message: message || '认证失败',
        };
      } else if (status === 403) {
        // 权限错误
        ctx.body = {
          code: 403,
          message: message || '权限不足',
        };
      } else if (status === 404) {
        // 资源不存在
        ctx.body = {
          code: 404,
          message: message || '资源不存在',
        };
      } else if (status === 409) {
        // 冲突错误
        ctx.body = {
          code: 409,
          message,
        };
      } else if (status === 503) {
        // 服务不可用
        ctx.body = {
          code: 503,
          message,
        };
      } else if (status >= 400 && status < 500) {
        // 客户端错误
        ctx.body = {
          code: status,
          message,
        };
      } else {
        // 服务器错误
        ctx.body = {
          code: 500,
          message: ctx.app.config.env === 'prod' ? '服务器内部错误' : message,
        };

        // 在开发环境下返回错误详情
        if (ctx.app.config.env !== 'prod') {
          ctx.body.details = {
            originalMessage: err.message,
            stack: err.stack,
            errorType,
          };
        }
      }

      // 记录详细错误信息到控制台（开发环境）
      if (ctx.app.config.env !== 'prod') {
        console.error('=== 错误详情 ===');
        console.error('URL:', ctx.method, ctx.url);
        console.error('错误类型:', errorType);
        console.error('状态码:', status);
        console.error('错误消息:', err.message);
        console.error('错误堆栈:', err.stack);
        console.error('================');
      }
    }
  };
};

// 检测错误类型
function detectErrorType(err) {
  const message = err.message || '';
  const name = err.name || '';
  const originalMessage = err.original?.message || '';

  // Sequelize 数据库错误
  if (name === 'SequelizeDatabaseError' || name.startsWith('Sequelize') ||
      message.includes('Unknown column') || originalMessage.includes('Unknown column')) {
    // 字段不存在错误
    if (message.includes('Unknown column') || originalMessage.includes('Unknown column')) {
      return 'SEQUELIZE_UNKNOWN_COLUMN';
    }
    // 表不存在错误
    if (message.includes("doesn't exist") || originalMessage.includes("doesn't exist")) {
      return 'SEQUELIZE_UNKNOWN_TABLE';
    }
    // 语法错误
    if (message.includes('syntax error') || originalMessage.includes('syntax error')) {
      return 'SEQUELIZE_SYNTAX_ERROR';
    }
    // 其他数据库错误
    return 'SEQUELIZE_DATABASE_ERROR';
  }

  // Sequelize 关联错误
  if (message.includes('is not associated to') ||
      message.includes('association') ||
      name === 'SequelizeEagerLoadingError') {
    return 'SEQUELIZE_ASSOCIATION';
  }

  // Sequelize 验证错误
  if (name === 'SequelizeValidationError') {
    return 'SEQUELIZE_VALIDATION';
  }

  // Sequelize 唯一性约束错误
  if (name === 'SequelizeUniqueConstraintError') {
    return 'SEQUELIZE_UNIQUE';
  }

  // Sequelize 外键约束错误
  if (name === 'SequelizeForeignKeyConstraintError') {
    return 'SEQUELIZE_FOREIGN_KEY';
  }

  // JWT 相关错误
  if (name === 'JsonWebTokenError' ||
      name === 'TokenExpiredError' ||
      name === 'NotBeforeError') {
    return 'JWT_ERROR';
  }

  // MySQL 连接错误
  if (message.includes('ECONNREFUSED') ||
      message.includes('ETIMEDOUT') ||
      message.includes('connect ECONNREFUSED')) {
    return 'MYSQL_CONNECTION';
  }

  return 'UNKNOWN';
}

// 获取错误消息
function getErrorMessage(err) {
  // 如果有自定义消息，优先使用
  if (err.message && err.message !== 'Internal Server Error') {
    return err.message;
  }

  // 对于 Sequelize 错误，尝试从 original 中获取更详细的信息
  if (err.name === 'SequelizeDatabaseError' && err.original) {
    return err.original.message || err.message || '数据库操作失败';
  }

  // 对于其他 Sequelize 错误
  if (err.name && err.name.startsWith('Sequelize')) {
    return err.message || '数据库操作失败';
  }

  // 默认消息
  return err.message || '服务器内部错误';
}
